#!/bin/bash
#
# CP2K Darwin arch file for a serial arm64 binary
# (https://www.cp2k.org/howto:compile_on_macos)
#
# Tested with: GNU 15.2.0 on an Apple M1 (macOS 15.6 Sequoia)
#
# Usage: Source this arch file and then run make as instructed.
#        Ensure the links in /opt/homebrew/bin to the gcc version.
#
# Last update: 06.10.2025
#
# \
   if [[ "${0}" == "${BASH_SOURCE}" ]]; then \
      echo "ERROR: Script ${0##*/} must be sourced"; \
      echo "Usage: source ${0##*/}"; \
      exit 1; \
   fi; \
   this_file=${BASH_SOURCE##*/}; \
   cd tools/toolchain; \
   rm -rf build; \
   [[ -z "${target_cpu}" ]] && target_cpu="native"; \
   if $(command -v brew >/dev/null 2>&1); then \
      brew install cmake; \
      brew install coreutils; \
      brew install fftw; \
      brew install gawk; \
      brew install gcc; \
      brew install hdf5; \
      brew install libaec; \
      brew install libxc; \
      brew install ninja; \
      brew install openblas; \
      brew install pkg-config; \
      brew install wget; \
      brew install zlib; \
   else \
      echo "ERROR: Homebrew installation not found"; \
      echo '  Run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'; \
      cd ../..; \
      return 1; \
   fi; \
   ./install_cp2k_toolchain.sh -j${maxtasks} --mpi-mode=no --no-arch-files --target-cpu=${target_cpu} \
      --with-cmake=$(brew --prefix cmake) --with-dftd4 --with-fftw=$(brew --prefix fftw) --with-gcc=system \
      --with-hdf5=$(brew --prefix hdf5) --with-libxc=$(brew --prefix libxc) --with-ninja=$(brew --prefix ninja) \
      --with-openblas=$(brew --prefix openblas) --with-trexio --with-libtorch=no --with-deepmd=no --with-tblite=no; \
   source ./install/setup; \
   cd ../..; \
   echo; \
   echo "Check the output above for error messages and consistency!"; \
   echo; \
   echo "If everything is OK, you can build a CP2K production binary with"; \
   echo "   make -j ARCH=${this_file%.*} VERSION=${this_file##*.} TARGET_CPU=${target_cpu}"; \
   echo; \
   echo "The Accelerate framework is used instead of OpenBLAS with"; \
   echo "   make -j ARCH=${this_file%.*} VERSION=${this_file##*.} TARGET_CPU=${target_cpu} USE_OPENBLAS="; \
   echo; \
   echo "Run always the following command before using the CP2K binary"; \
   echo "   source ${PWD}/tools/toolchain/install/setup"; \
   echo; \
   return

# Set options
DO_CHECKS      := no
TARGET_CPU     := native

# Retrieve package versions
GNU_VER        := $(shell gcc -dumpfullversion)
USE_DFTD4      := $(DFTD4_VER)
USE_LIBGRPP    := $(LIBGRPP_VER)
USE_LIBINT     := $(LIBINT_VER)
USE_LIBVORI    := $(LIBVORI_VER)
USE_LIBXSMM    := $(LIBXSMM_VER)
USE_OPENBLAS   := $(OPENBLAS_VER)
USE_SPGLIB     := $(SPGLIB_VER)
#USE_TBLITE     := $(TBLITE_VER)
USE_TREXIO     := $(TREXIO_VER)

LMAX           := 5
MAX_CONTR      := 4

CC             := gcc
CXX            := g++
FC             := gfortran
LD             := gfortran
AR             := ar -r -s

CFLAGS         := -O2 -fopenmp -fopenmp-simd -ftree-vectorize -funroll-loops -g -mtune=$(TARGET_CPU)

DFLAGS         += -D__MAX_CONTR=$(strip $(MAX_CONTR))
DFLAGS         += -D__NO_STATM_ACCESS

INSTALL_PATH   := $(PWD)/tools/toolchain/install

# Settings for regression testing
ifeq ($(DO_CHECKS), yes)
   DFLAGS         += -D__CHECK_DIAG
   FCFLAGS_DEBUG  := -fcheck=bounds,do,recursion,pointer
   FCFLAGS_DEBUG  += -fcheck=all,no-array-temps
#  FCFLAGS_DEBUG  += -ffpe-trap=invalid,overflow,zero
   FCFLAGS_DEBUG  += -fimplicit-none
   FCFLAGS_DEBUG  += -finit-derived
   FCFLAGS_DEBUG  += -finit-real=snan
   FCFLAGS_DEBUG  += -finit-integer=-42
   FCFLAGS_DEBUG  += -finline-matmul-limit=0
   WFLAGS         := -Werror=aliasing
   WFLAGS         += -Werror=ampersand
   WFLAGS         += -Werror=c-binding-type
   WFLAGS         += -Werror=conversion
   WFLAGS         += -Werror=intrinsic-shadow
   WFLAGS         += -Werror=intrinsics-std
   WFLAGS         += -Werror=line-truncation
   WFLAGS         += -Wrealloc-lhs
   WFLAGS         += -Werror=tabs
   WFLAGS         += -Werror=target-lifetime
   WFLAGS         += -Werror=underflow
   WFLAGS         += -Werror=unused-but-set-variable
   WFLAGS         += -Werror=unused-dummy-argument
   WFLAGS         += -Werror=unused-variable
endif

ifneq ($(USE_LIBVORI),)
   USE_LIBVORI    := $(strip $(USE_LIBVORI))
   LIBVORI_LIB    := $(INSTALL_PATH)/libvori-$(USE_LIBVORI)/lib
   DFLAGS         += -D__LIBVORI
   LIBS           += $(LIBVORI_LIB)/libvori.a
endif

LIBXC_HOME     := $(shell brew --prefix libxc)
CFLAGS         += -I$(LIBXC_HOME)/include
DFLAGS         += -D__LIBXC
LIBS           += -L$(LIBXC_HOME)/lib -lxcf03 -lxc

ifeq ($(USE_TBLITE),)
   ifneq ($(USE_DFTD4),)
      USE_DFTD4      := $(strip $(USE_DFTD4))
      DFTD4_INC      := $(INSTALL_PATH)/dftd4-$(USE_DFTD4)/include
      DFTD4_LIB      := $(INSTALL_PATH)/dftd4-$(USE_DFTD4)/lib
      CFLAGS         += -I$(DFTD4_INC)/dftd4/GNU-$(GNU_VER)
      DFLAGS         += -D__DFTD4
      LIBS           += $(DFTD4_LIB)/libdftd4.a
      LIBS           += $(DFTD4_LIB)/libmstore.a
      LIBS           += $(DFTD4_LIB)/libmulticharge.a
      LIBS           += $(DFTD4_LIB)/libmctc-lib.a
   endif
endif

ifneq ($(USE_LIBGRPP),)
   USE_LIBGRPP    := $(strip $(USE_LIBGRPP))
   DFLAGS         += -D__LIBGRPP
endif

ifneq ($(USE_LIBINT),)
   USE_LIBINT     := $(strip $(USE_LIBINT))
   LMAX           := $(strip $(LMAX))
   LIBINT_INC     := $(INSTALL_PATH)/libint-v$(USE_LIBINT)-cp2k-lmax-$(LMAX)/include
   LIBINT_LIB     := $(INSTALL_PATH)/libint-v$(USE_LIBINT)-cp2k-lmax-$(LMAX)/lib
   CFLAGS         += -I$(LIBINT_INC)
   DFLAGS         += -D__LIBINT
   LIBS           += $(LIBINT_LIB)/libint2.a
endif

ifneq ($(USE_SPGLIB),)
   USE_SPGLIB     := $(strip $(USE_SPGLIB))
   SPGLIB_INC     := $(INSTALL_PATH)/spglib-$(USE_SPGLIB)/include
   SPGLIB_LIB     := $(INSTALL_PATH)/spglib-$(USE_SPGLIB)/lib
   CFLAGS         += -I$(SPGLIB_INC)
   DFLAGS         += -D__SPGLIB
   LIBS           += $(SPGLIB_LIB)/libsymspg.a
endif

ifneq ($(USE_LIBXSMM),)
   USE_LIBXSMM    := $(strip $(USE_LIBXSMM))
   LIBXSMM_INC    := $(INSTALL_PATH)/libxsmm-$(USE_LIBXSMM)/include
   LIBXSMM_LIB    := $(INSTALL_PATH)/libxsmm-$(USE_LIBXSMM)/lib
   CFLAGS         += -I$(LIBXSMM_INC)
   DFLAGS         += -D__LIBXSMM
   LIBS           += $(LIBXSMM_LIB)/libxsmmf.a
   LIBS           += $(LIBXSMM_LIB)/libxsmmext.a
   LIBS           += $(LIBXSMM_LIB)/libxsmm.a
endif

FFTW_HOME      := $(shell brew --prefix fftw)
CFLAGS         += -I$(FFTW_HOME)/include
DFLAGS         += -D__FFTW3
LIBS           += $(FFTW_HOME)/lib/libfftw3_omp.a
LIBS           += $(FFTW_HOME)/lib/libfftw3.a

HDF5_HOME      := $(shell brew --prefix hdf5)
CFLAGS         += -I$(HDF5_HOME)/include
DFLAGS         += -D__HDF5
LIBS           += $(HDF5_HOME)/lib/libhdf5_fortran.a
LIBS           += $(HDF5_HOME)/lib/libhdf5_f90cstub.a
LIBS           += $(HDF5_HOME)/lib/libhdf5.a
LIBS           += $(shell brew --prefix zlib)/lib/libz.a
LIBS           += $(shell brew --prefix libaec)/lib/libsz.a

ifneq ($(USE_TBLITE),)
   USE_TBLITE     := $(strip $(USE_TBLITE))
   TBLITE_INC     := $(INSTALL_PATH)/tblite-$(USE_TBLITE)/include
   TBLITE_LIB     := $(INSTALL_PATH)/tblite-$(USE_TBLITE)/lib
   CFLAGS         += -I$(TBLITE_INC)/toml-f/modules
   CFLAGS         += -I$(TBLITE_INC)/mctc-lib/modules
   CFLAGS         += -I$(TBLITE_INC)/s-dftd3/GNU-$(GNU_VER)
   CFLAGS         += -I$(TBLITE_INC)/dftd4/GNU-$(GNU_VER)
   CFLAGS         += -I$(TBLITE_INC)/tblite/GNU-$(GNU_VER)
   DFLAGS         += -D__TBLITE
   DFLAGS         += -D__DFTD4
   LIBS           += $(TBLITE_LIB)/libtblite.a
   LIBS           += $(TBLITE_LIB)/libdftd4.a
   LIBS           += $(TBLITE_LIB)/libs-dftd3.a
   LIBS           += $(TBLITE_LIB)/libmulticharge.a
   LIBS           += $(TBLITE_LIB)/libmctc-lib.a
   LIBS           += $(TBLITE_LIB)/libtoml-f.a
endif

ifneq ($(USE_OPENBLAS),)
   OPENBLAS_HOME  := $(shell brew --prefix openblas)
   CFLAGS         += -I$(OPENBLAS_HOME)/include
   LIBS           += $(OPENBLAS_HOME)/lib/libopenblas.a
else
   # Linking to the Accelerate framework instead of OpenBLAS is not the default
   # because of failing tests
   DFLAGS         += -D__ACCELERATE
   LIBS           += -framework Accelerate
endif

ifneq ($(USE_TREXIO),)
   USE_TREXIO     := $(strip $(USE_TREXIO))
   TREXIO_INC     := $(INSTALL_PATH)/trexio-$(USE_TREXIO)/include
   TREXIO_LIB     := $(INSTALL_PATH)/trexio-$(USE_TREXIO)/lib
   CFLAGS         += -I$(TREXIO_INC)
   DFLAGS         += -D__TREXIO
   LIBS           += $(TREXIO_LIB)/libtrexio.a
endif

CFLAGS         += $(DFLAGS)

CXXFLAGS       := $(CFLAGS)

FCFLAGS        := $(CFLAGS) $(FCFLAGS_DEBUG) $(WFLAGS)
FCFLAGS        += -fallow-argument-mismatch
FCFLAGS        += -fbacktrace
FCFLAGS        += -ffree-form
FCFLAGS        += -ffree-line-length-none
FCFLAGS        += -fno-omit-frame-pointer
FCFLAGS        += -std=f2008

CFLAGS         += -std=c17
CXXFLAGS       += -std=c++17

LDFLAGS        := $(FCFLAGS)

LIBS           += -ldl -lstdc++

# End
